package com.legsem.jhosync.model;

import java.io.Serializable;
import java.io.StringReader;
import java.sql.Connection;
import java.sql.SQLException;

import org.apache.commons.dbutils.QueryRunner;
import org.h2.tools.RunScript;

public abstract class Model implements Serializable {

    private static final long serialVersionUID = 1L;

    /** Don't print complete strings if larger than this. */
    private static final int MAX_CHARS_TO_STRING = 64;

    public static QueryRunner run = new QueryRunner();

    public abstract int create() throws SQLException;

    public abstract int delete() throws SQLException;

    public abstract int update() throws SQLException;

    public static String toShortString(String longString) {
        if (longString == null || longString.length() <= MAX_CHARS_TO_STRING) {
            return longString;
        } else {
            StringBuilder sb = new StringBuilder();
            sb.append(longString.substring(0, MAX_CHARS_TO_STRING / 2));
            sb.append("...");
            sb.append(longString.substring(longString.length()
                    - MAX_CHARS_TO_STRING / 2));
            return sb.toString();
        }

    }

    /**
     * Drop tables and recreate them. Start with a brand new set of tables.
     * <p/>
     * Drop may fail if tables do not exist yet so we ignore that error.
     * <p/>
     * Create a set of predefined users.
     * 
     * @throws SQLException if creating tables fails.
     */
    public static void initSchema() throws SQLException {
        Connection conn = getConnection();
        StringReader reader = new StringReader(getDropDDL());
        try {
            RunScript.execute(conn, reader);
        } catch (SQLException e) {
            // On a new database, drop is expected to fail
        }
        reader = new StringReader(getCreateDDL());
        RunScript.execute(conn, reader);

        User.init();

    }

    public static String getDDL(boolean drop) {
        StringBuilder sb = new StringBuilder();
        if (drop) {
            sb.append(getDropDDL());
        }
        sb.append(getCreateDDL());
        return sb.toString();
    }

    public static String getDropDDL() {
        StringBuilder sb = new StringBuilder();
        sb.append(MasterDoc.getSqlDrop());
        sb.append(ClientDoc.getSqlDrop());
        sb.append(Client.getSqlDrop());
        sb.append(User.getSqlDrop());
        return sb.toString();
    }

    public static String getCreateDDL() {
        StringBuilder sb = new StringBuilder();
        sb.append(User.getSqlCreate());
        sb.append(MasterDoc.getSqlCreate());
        sb.append(Client.getSqlCreate());
        sb.append(ClientDoc.getSqlCreate());
        return sb.toString();
    }

    /**
     * @return an instance of a usable connection
     */
    public static Connection getConnection() {
        return ThreadLocalConnection.get();
    }
}
